//
/**
 * Filename: fig10-25_c_abort.c
 * Author:   csbonkers
 * Contact:  forever65535@qq.com
 * Date:     2021/6/20
 * Description:
 *    posix 标准的abort实现
 */
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// posix-style abort function
void c_abort() {
  sigset_t mask;
  struct sigaction act;
  // caller can't ignore SIGABRT, if so reset to SIG_DFL
  sigaction(SIGABRT, NULL, &act);
  if (act.sa_handler == SIG_IGN) {
    act.sa_handler = SIG_DFL;
    sigaction(SIGABRT, &act, NULL);
  }
  if (act.sa_handler == SIG_DFL) {
    fflush(NULL);// flush all open stdio stream
  }
  //caller can't block SIGABRT; make sure it's unblocked
  sigfillset(&mask);
  sigdelset(&mask, SIGABRT);            // mask has only SIGABRT turned off
  sigprocmask(SIG_SETMASK, &mask, NULL);// block all signal we can except SIGABRT
  kill(getpid(), SIGABRT);              // send the signal

  // if we're here, process caught SIGABRT and returned
  fflush(NULL);
  act.sa_handler = SIG_DFL;
  sigaction(SIGABRT, &act, NULL);       // reset to default
  sigprocmask(SIG_SETMASK, &mask, NULL);// just in case..
  kill(getpid(), SIGABRT);
  // never go here
  exit(1);
}
//static void sig_abrt(int signo){
//  printf("do something else");
//}
int main(int argc, char *argv[]) {
  printf("i love you");
  printf(",why you betray me.");
//  signal(SIGABRT, sig_abrt);
  sigset_t mask;
  sigemptyset(&mask);
  sigaddset(&mask, SIGABRT);
  sigprocmask(SIG_BLOCK, &mask, NULL);
  c_abort();
  return 0;
}



//    DESCRIPTION
//        The  abort()  function first unblocks the SIGABRT signal, and then raises that
//    signal for the calling process (as though raise(3) was called).  This  results
//    in the abnormal termination of the process unless the SIGABRT signal is caught
//        and the signal handler does not return (see longjmp(3)).
//
//    If the SIGABRT signal is ignored, or caught by a  handler  that  returns,  the
//    abort()  function will still terminate the process.  It does this by restoring
//        the default disposition for SIGABRT and then raising the signal for  a  second
//    time.